package cn.ichiva.test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class FastHttp {
    private Logger log = LoggerFactory.getLogger(FastHttp.class);

    String base = "";
    public FastHttp(){
        this("");
    }

    public FastHttp(String base){
        this.base = base;
    }

    public String getText(String url){
        return get(url,new HashMap<>());
    }

    public String getJson(String url){
        return get(url,new HashMap<>());
    }

    public String getText(String url, Map<String,String> params){
        HashMap<String, String> header = new HashMap<>();
        header.put("Content-Type", "text/plain");
        return get(url, header,params);
    }

    public String getJson(String url, Map<String,String> params){
        HashMap<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json");
        return get(url, header,params);
    }

    public String get(String url, Map<String,String> header,Map<String,String> params){
        String path = base + url;
        if(params.size() != 0){
            String paramsText = params.entrySet().stream()
                    .map(e -> String.format("%s=%s", e.getKey(), e.getValue()))
                    .collect(Collectors.joining("&"));

            path = path + "?" + paramsText;
        }

        return get(path,header);
    }

    public String post(String url, Map<String,String> header,Map<String,String> params){
        return post(url,header,JSON.toJSONString(params));
    }

    public String post(String path, Map<String,String> header,String postText) {
        URL urlObj;
        byte[] data = postText.getBytes(StandardCharsets.UTF_8);

        try {
            String url = base + path;
            log.info("post:{}", url);
            urlObj = new URL(url);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }

        HttpURLConnection conn;
        try {
            conn = (HttpURLConnection) urlObj.openConnection();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            conn.setRequestMethod("POST");
        } catch (ProtocolException e) {
            throw new RuntimeException(e);
        }
        conn.setConnectTimeout(5 * 1000);
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Length", String.valueOf(data.length));

        if(header.size() != 0){
            header.forEach((k,v) -> conn.setRequestProperty(k,v));
        }

        try (OutputStream out = conn.getOutputStream()){
            out.write(data);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        int code;
        try {
            code = conn.getResponseCode();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        if(code == 200){
            try (InputStream in = conn.getInputStream();
                 Reader reader = new InputStreamReader(in,StandardCharsets.UTF_8)){
                return IOUtils.readAll(reader);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        throw new RuntimeException("error:" + code);
    }

    private String get(String path, Map<String, String> header) {
        URL urlObj;
        try {
            String url = base + path;
            log.info("get:{}", url);
            urlObj = new URL(url);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }

        HttpURLConnection conn;
        try {
            conn = (HttpURLConnection) urlObj.openConnection();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            conn.setRequestMethod("GET");
        } catch (ProtocolException e) {
            throw new RuntimeException(e);
        }
        conn.setConnectTimeout(5 * 1000);

        if(header.size() != 0){
            header.forEach((k,v) -> conn.setRequestProperty(k,v));
        }

        int code;
        try {
            code = conn.getResponseCode();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        if(code == 200){
            try (InputStream in = conn.getInputStream();
                 Reader reader = new InputStreamReader(in,StandardCharsets.UTF_8)){
                return IOUtils.readAll(reader);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        throw new RuntimeException("error:" + code);
    }
}
